/*
 * File:   Network.cpp
 * Author: henrya
 *
 * Created on June 13, 2009, 8:43 PM
 */


#include "IOException.h"
#include "Tokenizer.h"
#include "Node.h"
#include "RuntimeException.h"
#include "Network.h"
#include <cstdlib>

Network::Network() {

}

Network* Network::createNetwork(ifstream& netConfStream, Shell* shell,Mailer* mailer) {
    Network* res = new Network();
    string nodeCountString;
    if (getline(netConfStream, nodeCountString) == 0) {
        RuntimeException ex("Network: Unexpected end of file or file format.");
        throw ex;
    }
    Tokenizer toknzr(nodeCountString);
    string* countString = toknzr.next();
    if (countString == NULL) {
        RuntimeException ex("Got NULL string will parsing node count.");
        throw ex;
    }
    res->nodeCount = atoi((*countString).c_str());
    if (res->nodeCount == 0) {
        RuntimeException ex("Node Count must be greater then 0.");
        throw ex;
    }
    string nodeConf;

    for (int nodesRead(0); nodesRead < res->nodeCount && getline(netConfStream, nodeConf) != 0; nodesRead++) {
        Node* newNode = Node::createNode(shell,mailer, res, nodeConf);
        res->nodes[newNode->getId()] = newNode;
        res->nodesIds.push_back(newNode->getId());
    }
    return res;
}

Network::~Network() {
}

int Network::getNodesCount() {
    return nodeCount;
}

vector<int>* Network::getNodeIds() {
    return &nodesIds;
}

void Network::printRTs() {
    for (map<int, Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) {
        (iter->second)->printRoutingTable();
    }
}

Node* Network::getNode(int id) {
    return nodes[id];
}

Node* Network::getNodeAt(unsigned int index) {
    return nodes[nodesIds.at(index)];
}

void Network::startNodes() {
    for (map<int, Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) {
        (iter->second)->start();
    }
}

bool Network::checkAllNodesStable() {

    for (map<int,Node*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
        if ((it->second)->getInboxSize() > 0) {
            return false;
        }
    }
    return true;
}

void Network::killAll() {

}
